﻿module VirtualCity.Setup.InputScripts

open Casanova
open Casanova.Utilities
open Casanova.Core
open Casanova.Coroutines
open Casanova.Game
open Casanova.Input
open Casanova.Math
open Casanova.Drawing
open VirtualCity
open VirtualCity.Scripts
open VirtualCity.Initialization
open VirtualCity.World
open VirtualCity.CityDescription
open VirtualCity.City
open VirtualCity.Rendering
open VirtualCity.PlanDescription
open Casanova.StandardLibrary.Core
open Casanova.StandardLibrary.Physics


let input_scripts automated_selection (slowdown_in_progress:Var<bool>) (world:World) exit =
  let move_speed = 100.0f
  [
    wait_key_press Keys.Escape =>> co{ return exit() }
    wait_key_press Keys.Left =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- (time_speed * 0.5f) |> max 60.0f 
      }
    wait_key_press Keys.Right =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- (time_speed * 2.0f) |> min 5000.0f 
      }

    wait_key_press Keys.R =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 1.0f 
      }
      
    wait_key_press Keys.OemTilde =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 0.01f 
      }
    wait_key_press Keys.D0 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 0.01f 
      }
    wait_key_press Keys.D1 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f 
      }
    wait_key_press Keys.D2 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *4.0f
      }
    wait_key_press Keys.D3 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *8.0f
      }
    wait_key_press Keys.D4 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *16.0f
      }
    wait_key_press Keys.D5 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *32.0f
      }
    wait_key_press Keys.D6 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 5000.0f //60.0f*83.333f
      }

    wait_key_press Keys.NumPad0 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 0.01f 
      }
    wait_key_press Keys.NumPad1 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f 
      }
    wait_key_press Keys.NumPad2 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *4.0f
      }
    wait_key_press Keys.NumPad3 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *8.0f
      }
    wait_key_press Keys.NumPad4 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *16.0f
      }
    wait_key_press Keys.NumPad5 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 60.0f *32.0f
      }
    wait_key_press Keys.NumPad6 =>> 
      co{ 
        if !slowdown_in_progress |> not then
          time_speed <- 5000.0f //60.0f*83.333f
      }

    wait_key_press Keys.Q =>> co{ world.Camera.Climb :=  20.0f<m/s> / time_speed }
    wait_key_press Keys.Z =>> co{ world.Camera.Climb := -20.0f<m/s> / time_speed }

    wait_key_press Keys.A =>> co{ world.Camera.Position := !world.Camera.Position + move_speed * Vector2.UnitX * !world.Camera.Height }
    wait_key_press Keys.D =>> co{ world.Camera.Position := !world.Camera.Position - move_speed * Vector2.UnitX * !world.Camera.Height }
    wait_key_press Keys.W =>> co{ world.Camera.Position := !world.Camera.Position + move_speed * Vector2.UnitY * !world.Camera.Height }
    wait_key_press Keys.S =>> co{ world.Camera.Position := !world.Camera.Position - move_speed * Vector2.UnitY * !world.Camera.Height }
    wait_left_mouse_press =>> 
      co{ 
        if not automated_selection then
          let mx,my = mouse_position()
          let mp = world.Layers.Agents.Unproject(Vector2.Create(mx,my))
          let closest = !world.City.Agents |> Seq.minBy (fun a -> Vector2.Distance(!a.Physical.Position, mp))
          match !world.Dashboard.SelectedAgent with
          | Some a -> (!a).Selected := false
          | _ -> ()
          do closest.Selected := true
          world.Dashboard.SelectedAgent := Some(ref closest)
          return ()
      }
    (wait_right_mouse_press .||> wait_key_press Keys.Back) =>> 
      co{ 
        if not automated_selection then
          match !world.Dashboard.SelectedAgent with
          | Some a -> (!a).Selected := false
          | _ -> ()
          world.Dashboard.SelectedAgent := None
          return ()
      }
  ]
